/*
 * List manipulations header file
 *
 * Copyright (C) 2020 Long-Horn.
 *
 */
#ifndef LIST_H
# define LIST_H

#ifdef __cplusplus
extern "C" {
#endif

#include <pthread.h>

typedef struct _node_s {
    struct node_s *prev;
    struct node_s *next;
    void *data;
} node_s;

typedef struct _list_s {
    pthread_mutex_t mutex;  // List's lock
    node_s *head;           // Points to first element of the list
    node_s *tail;           // Points to last element of the list
    unsigned int items;     // How many items are in the list
    char *name;
} list_s;

// Safe against calling list_del inside
#define list_for_each(list, elem, tmp_el) \
    for (elem = (list)->head->next, tmp_el = elem->next; elem != (list)->head && elem->data; elem = tmp_el, tmp_el = elem->next)

#define list_for_each_reverse(list, elem, tmp_el) \
    for (elem = (list)->head->prev, tmp_el = elem->prev; elem != (list)->head && elem->data; elem = tmp_el, tmp_el = elem->prev)

// list_del can not be called inside this for
#define list_for_each_unsafe(list, elem) \
    for (elem = (list)->head->next; elem != (list)->head && elem->data; elem = elem->next)

#define list_for_each_reverse_unsafe(list, elem) \
    for (elem = (list)->head->prev; elem != (list)->head && elem->data; elem = elem->prev)

list_s *list_new(char *listname);
void list_free(list_s **l, void (*l_free)(void *), void (*l_freep)(void **));

void list_lock(list_s *l);
void list_unlock(list_s *l);

void list_add(list_s *l, void *data);

int  list_del(list_s *l, node_s **node);
int  list_del_unlocked(list_s *l, node_s **node);

int  list_del_entry(list_s *l, void *data);

void list_dump(list_s *l);

#ifdef __cplusplus
}
#endif

#endif
